import json
import sys
import sqlite3
import socket
from datetime import datetime
from PyQt5.QtWidgets import (QApplication, QMainWindow, QDialog, QLabel, QPushButton,
                             QGridLayout, QVBoxLayout, QHBoxLayout, QWidget, QTableWidget,
                             QTableWidgetItem, QHeaderView, QLineEdit, QToolBar, QMessageBox, QSpinBox, QTextBrowser,
                             QInputDialog, QFileDialog)
from PyQt5.QtGui import QPixmap, QIcon
from PyQt5.QtCore import Qt, QSize
# 使用多线程模拟多个客户端连接
import threading


# ========================== 数据库模块 ==========================
def init_database():
    conn = sqlite3.connect('users.db')
    c = conn.cursor()
    # 创建用户表，添加新的个人资料字段
    c.execute('''
        CREATE TABLE IF NOT EXISTS users (
            user_id INTEGER PRIMARY KEY,
            username TEXT NOT NULL UNIQUE,
            avatar_path TEXT NOT NULL,
            password TEXT DEFAULT '123456',
            encoding_rule INTEGER DEFAULT 0,
            is_locked BOOLEAN DEFAULT 0,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            signature TEXT DEFAULT '这个人很懒，什么都没留下',
            email TEXT,
            phone TEXT,
            gender TEXT DEFAULT '未设置',
            birthday TEXT
        )
    ''')
    # 创建好友表
    c.execute('''
           CREATE TABLE IF NOT EXISTS friends (
               user_id INTEGER NOT NULL,
               friend_id INTEGER NOT NULL,
               status INTEGER DEFAULT 0, -- 0: 待确认, 1: 已接受, 2: 已拒绝
               remark TEXT, -- 好友备注
               created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
               PRIMARY KEY (user_id, friend_id),
               FOREIGN KEY (user_id) REFERENCES users(user_id),
               FOREIGN KEY (friend_id) REFERENCES users(user_id)
           )
       ''')
    # 创建消息表
    c.execute('''
           CREATE TABLE IF NOT EXISTS messages (
               msg_id INTEGER PRIMARY KEY,
               sender_id INTEGER NOT NULL,
               receiver_id INTEGER NOT NULL,
               content TEXT NOT NULL,
               msg_type TEXT DEFAULT 'text', -- text, image, file
               timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
               status INTEGER DEFAULT 0, -- 0: 未读, 1: 已读
               FOREIGN KEY (sender_id) REFERENCES users(user_id),
               FOREIGN KEY (receiver_id) REFERENCES users(user_id)
           )
       ''')
    # 创建收藏表
    c.execute('''
           CREATE TABLE IF NOT EXISTS favorites (
               favorite_id INTEGER PRIMARY KEY,
               user_id INTEGER NOT NULL,
               content TEXT NOT NULL,
               content_type TEXT DEFAULT 'text', -- text, image, file
               created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
               FOREIGN KEY (user_id) REFERENCES users(user_id)
           )
       ''')
    # 插入测试数据
    users = [
        (101, 'zhjw', 'avatar1.jpg', '123456', 0, 0, '2025-01-11 18:00:00', '开心每一天', 'zhjw@example.com',
         '13800138000', '男', '2000-01-01'),
        (102, '华航', 'avatar2.jpg', '123456', 0, 0, '2025-01-11 18:00:00', '追求卓越', 'huahang@example.com',
         '13800138001', '男', '2000-02-02'),
        (195858288, 'besti', 'avatar3.jpg', '123456', 0, 0, '2025-01-11 18:00:00', '热爱生活', 'besti@example.com',
         '13800138002', '女', '2000-03-03'),
    ]
    try:
        c.executemany(
            'INSERT INTO users (user_id, username, avatar_path, password, encoding_rule, is_locked, created_at, signature, email, phone, gender, birthday) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)',
            users)
    except sqlite3.IntegrityError:
        pass  # 防止重复插入
    conn.commit()
    conn.close()


# ========================== 服务器主界面 ==========================
class ServerWindow(QMainWindow):
    def __init__(self):
        """初始化服务器"""
        super().__init__()
        self.setWindowTitle("cutychat-服务器")
        self.setWindowIcon(QIcon("kitty.png"))
        self.resize(1500, 1000)

        # 初始化成员变量
        self.online_users = {}  # 在线用户字典
        self.lock = threading.Lock()
        self.is_listening = False
        self.server_socket = None

        # 初始化数据库
        init_database()  # 调用全局函数初始化数据库
        self.test_database_connection()

        # 初始化UI
        self.init_ui()

    def init_database(self):
        """初始化数据库连接"""
        try:
            conn = sqlite3.connect('users.db')
            c = conn.cursor()
            # 测试数据库连接
            c.execute('SELECT 1')
            conn.close()
            print("数据库连接正常")
        except Exception as e:
            print(f"数据库连接失败: {e}")
            QMessageBox.critical(self, "错误", f"数据库连接失败: {e}")
            raise

    def test_database_connection(self):
        """测试数据库连接"""
        try:
            conn = sqlite3.connect('users.db')
            c = conn.cursor()
            c.execute('SELECT * FROM users LIMIT 1')
            result = c.fetchone()
            print("数据库连接测试成功")
            print(f"测试查询结果: {result}")
            conn.close()
        except Exception as e:
            print(f"数据库连接测试失败: {e}")
            QMessageBox.critical(self, "错误", f"数据库连接测试失败: {e}")
            raise

    def handle_client(self, client_socket):
        """处理客户端连接"""
        print("\n=== 新的客户端连接 ===")
        client_address = client_socket.getpeername()
        print(f"客户端地址: {client_address}")

        try:
            while True:
                try:
                    data = client_socket.recv(4096)
                    if not data:
                        print(f"客户端 {client_address} 断开连接（接收到空数据）")
                        break

                    print(f"\n收到数据: {data}")
                    request = json.loads(data.decode())
                    print(f"解析后的请求: {request}")

                    # 处理请求
                    self.process_request(client_socket, request)

                except json.JSONDecodeError as e:
                    print(f"JSON解析错误: {e}")
                    continue
                except socket.timeout:
                    # 超时是正常的，继续等待
                    continue
                except ConnectionError as e:
                    print(f"连接错误: {e}")
                    break
                except Exception as e:
                    print(f"处理客户端请求时出错: {e}")
                    import traceback
                    print(traceback.format_exc())
                    break
        except Exception as e:
            print(f"客户端处理线程异常: {e}")
        finally:
            try:
                # 从在线用户列表中移除
                with self.lock:
                    for user_id, sock in list(self.online_users.items()):
                        if sock == client_socket:
                            del self.online_users[user_id]
                            print(f"用户 {user_id} 已从在线列表移除")
                            break
                client_socket.close()
                print(f"客户端 {client_address} 连接已关闭")
            except:
                pass

    def process_request(self, socket, request):
        """处理客户端请求"""
        req_type = request.get('type')
        print(f"处理请求类型: {req_type}")  # 添加调试信息

        try:
            if req_type == 'login':
                self.handle_login(socket, request)
            elif req_type == 'register':
                self.handle_register(socket, request)
            elif req_type == 'recover_password':
                self.handle_recover_password(socket, request)
            elif req_type == 'search':
                self.handle_search(socket, request)
            elif req_type == 'message':
                self.handle_message(request)
            elif req_type == 'add_friend':
                self.handle_add_friend(socket, request)
            elif req_type == 'accept_friend':
                self.handle_accept_friend(socket, request)
            elif req_type == 'update_profile':
                self.handle_update_profile(socket, request)
            elif req_type == 'get_friends':
                self.handle_get_friends(socket, request)
            else:
                print(f"未知的请求类型: {req_type}")
        except Exception as e:
            print(f"处理请求时发生错误: {e}")
            # 发送错误响应
            try:
                error_response = {
                    'type': f'{req_type}_response' if req_type else 'error_response',
                    'status': 'error',
                    'message': str(e)
                }
                socket.send(json.dumps(error_response).encode())
            except Exception as send_error:
                print(f"发送错误响应失败: {send_error}")
                pass

    def get_user_friends(self, user_id):
        """获取用户的好友列表"""
        friends = []
        try:
            conn = sqlite3.connect('users.db')
            c = conn.cursor()

            # 获取已接受的好友关系
            c.execute('''
                SELECT u.user_id, u.username, u.avatar_path, u.signature, f.remark
                FROM friends f
                JOIN users u ON f.friend_id = u.user_id
                WHERE f.user_id = ? AND f.status = 1
            ''', (user_id,))

            for row in c.fetchall():
                friends.append({
                    'user_id': row[0],
                    'username': row[1],
                    'avatar_path': row[2],
                    'signature': row[3],
                    'remark': row[4] or row[1]  # 如果没有备注就使用用户名
                })

        except Exception as e:
            print(f"获取好友列表失败: {e}")
        finally:
            conn.close()

        return friends

    def get_username(self, user_id):
        """根据用户ID获取用户名"""
        try:
            conn = sqlite3.connect('users.db')
            c = conn.cursor()
            c.execute('SELECT username FROM users WHERE user_id = ?', (user_id,))
            result = c.fetchone()
            return result[0] if result else "未知用户"
        except Exception as e:
            print(f"获取用户名失败: {e}")
            return "未知用户"
        finally:
            conn.close()

    def handle_login(self, socket, request):
        """处理登录请求（完整验证逻辑）"""
        user_id = request.get('user_id')
        password = request.get('password')
        login_success = False
        print(f"收到登录请求 - 用户ID: {user_id}")  # 添加调试信息

        try:
            conn = sqlite3.connect('users.db')
            c = conn.cursor()
            # 修改查询语句包含所有用户信息
            c.execute('''
                SELECT user_id, username, password, is_locked, avatar_path, signature, 
                       email, phone, gender, birthday
                FROM users
                WHERE user_id = ?
            ''', (user_id,))
            user = c.fetchone()
            print(f"查询到的用户信息: {user}")  # 添加调试信息

            response = {}
            if user:
                if user[3]:  # 检查账户锁定状态
                    response = {
                        'type': 'login_response',
                        'status': 'error',
                        'message': '账户已被锁定'
                    }
                elif user[2] == password:  # 验证密码
                    login_success = True
                    friends = self.get_user_friends(user_id)
                    # 获取未处理的好友请求
                    friend_requests = self.get_friend_requests(user_id)
                    response = {
                        'type': 'login_response',
                        'status': 'success',
                        'user_id': user[0],
                        'username': user[1],
                        'avatar_path': user[4],
                        'signature': user[5],
                        'email': user[6],
                        'phone': user[7],
                        'gender': user[8],
                        'birthday': user[9],
                        'friends': friends,
                        'friend_requests': friend_requests  # 添加好友请求列表
                    }
                    print(f"登录成功，准备发送响应: {response}")  # 添加调试信息
                else:
                    response = {
                        'type': 'login_response',
                        'status': 'error',
                        'message': '密码错误'
                    }
            else:
                response = {
                    'type': 'login_response',
                    'status': 'error',
                    'message': '用户不存在'
                }

        except Exception as e:
            print(f"登录处理发生错误: {str(e)}")  # 添加调试信息
            response = {
                'type': 'login_response',
                'status': 'error',
                'message': f'数据库错误: {str(e)}'
            }
        finally:
            conn.close()

        # 更新在线用户列表
        if login_success:
            with self.lock:
                self.online_users[user_id] = socket
                print(f"用户 {user_id} 已添加到在线用户列表")  # 添加调试信息

        # 发送响应
        try:
            socket.send(json.dumps(response).encode())
            print("登录响应已发送")  # 添加调试信息
        except Exception as e:
            print(f"发送登录响应失败: {e}")

    def handle_search(self, socket, request):
        """处理用户搜索请求"""
        keyword = request.get('keyword', '')
        current_user_id = request.get('current_user_id')  # 添加当前用户ID
        search_results = []

        print(f"\n=== 处理搜索请求 ===")
        print(f"关键词: {keyword}")
        print(f"当前用户ID: {current_user_id}")

        try:
            conn = sqlite3.connect('users.db')
            c = conn.cursor()

            # 尝试将关键词转换为整数（用户ID）
            try:
                user_id = int(keyword)
                # 精确匹配用户ID，排除自己
                c.execute('''
                    SELECT user_id, username, avatar_path, signature
                    FROM users
                    WHERE user_id = ? AND user_id != ?
                ''', (user_id, current_user_id))
                print(f"执行ID精确搜索: {user_id}")
            except ValueError:
                # 如果不是数字，则按用户名模糊搜索，排除自己
                c.execute('''
                    SELECT user_id, username, avatar_path, signature
                    FROM users
                    WHERE username LIKE ? AND user_id != ?
                    LIMIT 20
                ''', (f'%{keyword}%', current_user_id))
                print(f"执行用户名模糊搜索: {keyword}")

            results = c.fetchall()
            print(f"查询结果数量: {len(results)}")

            for row in results:
                result = {
                    'user_id': row[0],
                    'username': row[1],
                    'avatar_path': row[2],
                    'signature': row[3] if row[3] else '这个人很懒，什么都没留下'
                }
                print(f"处理搜索结果: {result}")
                search_results.append(result)

        except Exception as e:
            print(f"搜索失败: {e}")
            import traceback
            print(traceback.format_exc())
        finally:
            conn.close()

        response = {
            'type': 'search_result',
            'data': search_results
        }
        print(f"发送搜索响应: {response}")
        socket.send(json.dumps(response).encode())
        print("=== 搜索请求处理完成 ===\n")

    def handle_message(self, request):
        receiver_id = request.get('to')
        sender_id = request.get('from')
        if receiver_id in self.online_users:
            receiver_socket = self.online_users[receiver_id]
            if 'from' in request and 'content' in request:
                receiver_socket.send(json.dumps({
                    'type': 'message',
                    'from': request['from'],
                    'content': request['content']
                }).encode())
            else:
                print("消息格式错误，缺少必要字段")
            # 存储消息到数据库
        conn = sqlite3.connect('users.db')
        try:
            c = conn.cursor()
            c.execute('''
                  INSERT INTO messages (sender_id, receiver_id, content, timestamp)
                  VALUES (?, ?, ?, ?)
              ''', (sender_id, receiver_id, request['content'], datetime.now()))
            conn.commit()
        except Exception as e:
            print(f"消息存储失败: {e}")
        finally:
            conn.close()
            # 增加必要字段验证
        if not all(key in request for key in ['from', 'to', 'content']):
            print("无效的消息格式")
            return

        # # 转发消息（原有逻辑不变）
        # if receiver_id in self.online_users:

    # ...保持原有转发代码...

    def handle_add_friend(self, socket, request):
        """处理添加好友请求"""
        user_id = request.get('user_id')
        friend_id = request.get('friend_id')

        try:
            conn = sqlite3.connect('users.db')
            c = conn.cursor()

            # 检查是否已经是好友
            c.execute('''
                SELECT status FROM friends 
                WHERE (user_id = ? AND friend_id = ?) 
                OR (user_id = ? AND friend_id = ?)
            ''', (user_id, friend_id, friend_id, user_id))
            result = c.fetchone()

            if result:
                if result[0] == 1:
                    response = {
                        'type': 'add_friend_response',
                        'status': 'error',
                        'message': '已经是好友关系'
                    }
                else:
                    response = {
                        'type': 'add_friend_response',
                        'status': 'error',
                        'message': '好友请求处理中'
                    }
            else:
                # 添加好友请求
                c.execute('''
                    INSERT INTO friends (user_id, friend_id, status)
                    VALUES (?, ?, 0)
                ''', (user_id, friend_id))
                conn.commit()

                # 获取发送请求的用户信息
                c.execute('SELECT username FROM users WHERE user_id = ?', (user_id,))
                username = c.fetchone()[0]

                response = {
                    'type': 'add_friend_response',
                    'status': 'success',
                    'message': '好友请求已发送'
                }

                # 如果对方在线，发送好友请求通知
                if friend_id in self.online_users:
                    friend_socket = self.online_users[friend_id]
                    notification = {
                        'type': 'friend_request',
                        'from_user_id': user_id,
                        'from_username': username
                    }
                    friend_socket.send(json.dumps(notification).encode())

        except Exception as e:
            response = {
                'type': 'add_friend_response',
                'status': 'error',
                'message': f'添加好友失败: {str(e)}'
            }
        finally:
            conn.close()

        socket.send(json.dumps(response).encode())

    def handle_accept_friend(self, socket, request):
        """处理接受好友请求"""
        user_id = request.get('user_id')
        friend_id = request.get('friend_id')
        accept = request.get('accept', True)

        try:
            conn = sqlite3.connect('users.db')
            c = conn.cursor()

            if accept:
                # 获取接受者的用户名
                c.execute('SELECT username, avatar_path FROM users WHERE user_id = ?', (user_id,))
                user_info = c.fetchone()
                username = user_info[0]
                avatar_path = user_info[1]

                # 更新好友关系状态为已接受
                c.execute('''
                    UPDATE friends 
                    SET status = 1 
                    WHERE user_id = ? AND friend_id = ?
                ''', (friend_id, user_id))

                # 添加反向的好友关系
                c.execute('''
                    INSERT INTO friends (user_id, friend_id, status)
                    VALUES (?, ?, 1)
                ''', (user_id, friend_id))

                conn.commit()

                response = {
                    'type': 'accept_friend_response',
                    'status': 'success',
                    'message': '已添加为好友'
                }

                # 通知请求发送者
                if friend_id in self.online_users:
                    friend_socket = self.online_users[friend_id]
                    notification = {
                        'type': 'friend_accepted',
                        'friend_id': user_id,
                        'friend_username': username,
                        'avatar_path': avatar_path
                    }
                    friend_socket.send(json.dumps(notification).encode())
            else:
                # 更新好友关系状态为已拒绝
                c.execute('''
                    UPDATE friends 
                    SET status = 2 
                    WHERE user_id = ? AND friend_id = ?
                ''', (friend_id, user_id))
                conn.commit()

                response = {
                    'type': 'accept_friend_response',
                    'status': 'success',
                    'message': '已拒绝好友请求'
                }

        except Exception as e:
            response = {
                'type': 'accept_friend_response',
                'status': 'error',
                'message': f'处理好友请求失败: {str(e)}'
            }
        finally:
            conn.close()

        socket.send(json.dumps(response).encode())

    def handle_register(self, socket, request):
        """处理用户注册请求"""
        user_id = request.get('user_id')
        username = request.get('username')
        password = request.get('password')

        try:
            conn = sqlite3.connect('users.db')
            c = conn.cursor()

            # 检查用户ID是否已存在
            c.execute('SELECT user_id FROM users WHERE user_id = ?', (user_id,))
            if c.fetchone():
                response = {
                    'type': 'register_response',
                    'status': 'error',
                    'message': '用户ID已存在'
                }
            else:
                # 检查用户名是否已存在
                c.execute('SELECT username FROM users WHERE username = ?', (username,))
                if c.fetchone():
                    response = {
                        'type': 'register_response',
                        'status': 'error',
                        'message': '用户名已存在'
                    }
                else:
                    # 插入新用户
                    c.execute('''
                        INSERT INTO users (user_id, username, password, avatar_path)
                        VALUES (?, ?, ?, ?)
                    ''', (user_id, username, password, 'avatar1.jpg'))
                    conn.commit()
                    response = {
                        'type': 'register_response',
                        'status': 'success',
                        'message': '注册成功'
                    }
        except Exception as e:
            response = {
                'type': 'register_response',
                'status': 'error',
                'message': f'注册失败: {str(e)}'
            }
        finally:
            conn.close()

        socket.send(json.dumps(response).encode())

    def handle_recover_password(self, socket, request):
        """处理找回密码请求"""
        user_id = request.get('user_id')

        try:
            conn = sqlite3.connect('users.db')
            c = conn.cursor()

            # 查找用户
            c.execute('SELECT password FROM users WHERE user_id = ?', (user_id,))
            result = c.fetchone()

            if result:
                # 在实际应用中，这里应该发送邮件或短信
                # 这里为了演示，直接返回密码
                response = {
                    'type': 'recover_password_response',
                    'status': 'success',
                    'message': f'您的密码是: {result[0]}'
                }
            else:
                response = {
                    'type': 'recover_password_response',
                    'status': 'error',
                    'message': '用户不存在'
                }
        except Exception as e:
            response = {
                'type': 'recover_password_response',
                'status': 'error',
                'message': f'找回密码失败: {str(e)}'
            }
        finally:
            conn.close()

        socket.send(json.dumps(response).encode())

    def handle_update_profile(self, socket, request):
        """处理更新个人资料请求"""
        user_id = request.get('user_id')
        updates = request.get('updates', {})

        try:
            conn = sqlite3.connect('users.db')
            c = conn.cursor()

            # 构建更新语句
            update_fields = []
            update_values = []
            for field, value in updates.items():
                if field in ['username', 'avatar_path', 'signature', 'email', 'phone', 'gender', 'birthday']:
                    update_fields.append(f"{field} = ?")
                    update_values.append(value)

            if update_fields:
                update_values.append(user_id)
                update_sql = f"UPDATE users SET {', '.join(update_fields)} WHERE user_id = ?"
                c.execute(update_sql, update_values)
                conn.commit()

                response = {
                    'type': 'update_profile_response',
                    'status': 'success',
                    'message': '个人资料更新成功'
                }
            else:
                response = {
                    'type': 'update_profile_response',
                    'status': 'error',
                    'message': '没有要更新的字段'
                }
        except Exception as e:
            response = {
                'type': 'update_profile_response',
                'status': 'error',
                'message': f'更新失败: {str(e)}'
            }
        finally:
            conn.close()

        socket.send(json.dumps(response).encode())

    def handle_get_friends(self, socket, request):
        """处理获取好友列表请求"""
        user_id = request.get('user_id')
        try:
            friends = self.get_user_friends(user_id)
            response = {
                'type': 'friends_list',
                'friends': friends
            }
            socket.send(json.dumps(response).encode())
        except Exception as e:
            print(f"获取好友列表失败: {e}")
            response = {
                'type': 'friends_list',
                'friends': []
            }
            socket.send(json.dumps(response).encode())

    def init_ui(self):
        # 顶部工具栏
        toolbar = QToolBar()
        self.addToolBar(toolbar)
        self.user_manage_btn = QPushButton(QIcon("用户.png"), "用户管理")
        self.port_label = QLabel("监听端口：")
        self.spinbox = QSpinBox()
        self.spinbox.setMinimum(0)  # 最小值
        self.spinbox.setMaximum(10000)  # 最大值
        self.spinbox.setValue(8888)  # 修改为8888端口
        # 监听控制按钮
        self.listen_start = QPushButton(self)
        self.listen_start.setIcon(QIcon("start.png"))  # 初始图标为启动
        self.listen_start.setFixedSize(64, 64)  # 设置固定大小
        self.listen_start.setStyleSheet("""
                    QPushButton {
                        background-color: transparent;
                        border: none;
                    }
                """)  # 透明无边框样式

        toolbar.addSeparator()  # 在动作之间添加分隔线
        toolbar.addWidget(self.user_manage_btn)
        toolbar.addWidget(self.port_label)
        toolbar.addWidget(self.spinbox)
        toolbar.addWidget(self.listen_start)

        # 用户头像网格布局
        self.grid_layout = QGridLayout()
        self.grid_layout.setSpacing(15)  # 设置间距
        self.load_users()  # 加载用户数据

        # 底部信息显示区域
        self.info_browser = QTextBrowser()
        # self.info_browser.setPlaceholderText("监听日志将显示在此处...")
        self.info_browser.setMinimumHeight(280)  # 最小高度
        self.info_browser.setStyleSheet("""
                QTextBrowser {
                    background-color: white;
                    border-top: 1px solid #dee2e6;
                    font-family: '微软雅黑';
                    font-size: 30px;
                }
            """)  # 修改背景颜色为白色，添加分割线

        central_widget = QWidget()
        main_layout = QVBoxLayout()
        # 创建一个新的QWidget用于放置头像区域，并设置背景为白色
        avatar_widget = QWidget()
        avatar_widget.setStyleSheet("background-color: white;")
        avatar_layout = QVBoxLayout(avatar_widget)
        avatar_layout.addLayout(self.grid_layout)
        main_layout.addWidget(avatar_widget, 3)  # 调整比例
        main_layout.addWidget(self.info_browser, 2)
        central_widget.setLayout(main_layout)
        self.setCentralWidget(central_widget)

        # 事件绑定
        self.user_manage_btn.clicked.connect(self.open_user_manage)
        self.listen_start.clicked.connect(self.toggle_listen)

    def load_users(self):
        conn = sqlite3.connect('users.db')
        c = conn.cursor()
        c.execute("SELECT username, avatar_path FROM users")
        users = c.fetchall()

        row, col = 0, 0
        for idx, (username, avatar_path) in enumerate(users):
            # 创建单个用户容器（垂直布局）
            user_widget = QWidget()
            user_layout = QVBoxLayout()
            # user_layout.setSpacing(8)  # 增大头像与文字的距离
            user_layout.setContentsMargins(5, 5, 5, 5)  # 设置单个用户区块的内边距

            # 头像
            avatar_label = QLabel()
            pixmap = QPixmap(avatar_path).scaled(400, 200, Qt.KeepAspectRatio)  # 保持比例
            avatar_label.setPixmap(pixmap)
            avatar_label.setAlignment(Qt.AlignCenter)
            user_layout.addWidget(avatar_label)

            # 用户名
            name_label = QLabel(username)
            name_label.setAlignment(Qt.AlignCenter)
            name_label.setStyleSheet("font-size: 27px;")  # 设置文字大小
            user_layout.addWidget(name_label)

            user_widget.setLayout(user_layout)

            # 添加到网格
            self.grid_layout.addWidget(user_widget, row, col)

            col += 1
            if col >= 5:  # 每行显示5个用户
                col = 0
                row += 1  # 行数递增方式改为+1
        conn.close()

    def open_user_manage(self):
        self.user_manage_ui = UserManageWindow()
        self.user_manage_ui.show()

    def toggle_listen(self):
        if self.is_listening:
            self.stop_listening()
        else:
            self.start_listening()

    def start_listening(self):
        """启动服务器监听"""
        try:
            port = self.spinbox.value()
            print(f"尝试在端口 {port} 上启动服务器...")

            # 检查端口占用
            test_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            try:
                test_socket.bind(('0.0.0.0', port))
                test_socket.close()
            except OSError as e:
                print(f"端口 {port} 已被占用: {e}")
                QMessageBox.critical(self, "错误", f"端口 {port} 已被占用")
                return

            # 创建服务器套接字
            self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.server_socket.bind(('0.0.0.0', port))
            self.server_socket.listen(5)
            self.server_socket.settimeout(1)  # 设置超时，以便能够正常关闭

            # 更新状态
            self.is_listening = True
            self.listen_start.setIcon(QIcon("stop.png"))
            self.info_browser.append(f"✅ 成功监听端口 {port}")
            print(f"服务器已在端口 {port} 上启动")

            # 启动接受连接的线程
            threading.Thread(target=self.accept_connections, daemon=True).start()

        except Exception as e:
            print(f"启动服务器失败: {e}")
            self.info_browser.append(f"❌ 启动失败: {str(e)}")
            QMessageBox.critical(self, "错误", f"启动服务器失败: {str(e)}")

    def stop_listening(self):
        """停止服务器监听"""
        try:
            print("正在停止服务器...")
            self.is_listening = False

            # 关闭所有客户端连接
            with self.lock:
                for user_id, sock in list(self.online_users.items()):
                    try:
                        sock.close()
                        print(f"已关闭用户 {user_id} 的连接")
                    except Exception as e:
                        print(f"关闭用户 {user_id} 连接时出错: {e}")
                self.online_users.clear()

            # 关闭服务器套接字
            if self.server_socket:
                try:
                    self.server_socket.close()
                    print("服务器套接字已关闭")
                except Exception as e:
                    print(f"关闭服务器套接字时出错: {e}")
                self.server_socket = None

            self.info_browser.append("✅ 已停止监听")
            self.listen_start.setIcon(QIcon("start.png"))
            print("服务器已停止")

        except Exception as e:
            print(f"停止服务器时出错: {e}")
            self.info_browser.append(f"停止监听失败: {str(e)}")

    def accept_connections(self):
        """接受客户端连接"""
        print("开始接受客户端连接...")
        while self.is_listening:
            try:
                client, addr = self.server_socket.accept()
                print(f"收到新的连接请求: {addr}")
                client.settimeout(5)  # 设置客户端套接字超时
                self.info_browser.append(f"新连接: {addr[0]}:{addr[1]}")

                # 启动新线程处理客户端
                client_thread = threading.Thread(
                    target=self.handle_client,
                    args=(client,),
                    daemon=True
                )
                client_thread.start()
                print(f"已启动新线程处理客户端 {addr}")

            except socket.timeout:
                # 超时是正常的，继续等待新连接
                continue
            except Exception as e:
                if self.is_listening:
                    print(f"接受连接时出错: {e}")
                else:
                    # 服务器已停止，退出循环
                    break

        print("停止接受客户端连接")

    def get_friend_requests(self, user_id):
        """获取用户收到的好友请求"""
        requests = []
        try:
            conn = sqlite3.connect('users.db')
            c = conn.cursor()

            # 获取待处理的好友请求
            c.execute('''
                SELECT u.user_id, u.username, u.avatar_path
                FROM friends f
                JOIN users u ON f.user_id = u.user_id
                WHERE f.friend_id = ? AND f.status = 0
            ''', (user_id,))

            for row in c.fetchall():
                requests.append({
                    'user_id': row[0],
                    'username': row[1],
                    'avatar_path': row[2]
                })

        except Exception as e:
            print(f"获取好友请求失败: {e}")
        finally:
            conn.close()

        return requests


# ========================== 用户管理界面 ==========================
class UserManageWindow(QDialog):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("用户管理")
        self.setWindowIcon(QIcon("用户管理.png"))  # 设置图标
        self.resize(1500, 800)
        # self.setGeometry(200, 200, 1000, 600)
        self.init_ui()

    def init_ui(self):
        # 表格
        self.table = QTableWidget()
        self.table.setColumnCount(7)
        self.table.setHorizontalHeaderLabels(["用户ID", "用户名", "头像", "密码", "编码规则", "锁定", "创建时间"])
        self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.load_data()

        # 操作按钮
        btn_layout = QVBoxLayout()
        self.add_btn = QPushButton(QIcon("添加用户.png"), "添加")
        self.del_btn = QPushButton(QIcon("删除用户.png"), "删除")
        self.exit_btn = QPushButton(QIcon("退出.png"), "退出")
        btn_layout.addWidget(self.add_btn)
        btn_layout.addWidget(self.del_btn)
        btn_layout.addStretch()
        btn_layout.addWidget(self.exit_btn)

        # 主布局
        main_layout = QHBoxLayout()
        main_layout.addWidget(self.table, 70)
        main_layout.addLayout(btn_layout, 30)
        self.setLayout(main_layout)

        # 事件绑定
        self.add_btn.clicked.connect(self.add_user)
        self.del_btn.clicked.connect(self.delete_user)
        self.exit_btn.clicked.connect(self.close)

    def load_data(self):
        conn = sqlite3.connect('users.db')
        c = conn.cursor()
        c.execute("SELECT * FROM users")
        users = c.fetchall()

        self.table.setRowCount(len(users))
        for row_idx, user in enumerate(users):
            for col_idx, data in enumerate(user):
                item = QTableWidgetItem(str(data))
                # 特殊字段处理
                if col_idx == 2:  # 头像列显示图片
                    pixmap = QPixmap(data).scaled(40, 40)
                    item.setIcon(QIcon(pixmap))
                elif col_idx == 5:  # 锁定列显示复选框
                    item.setCheckState(Qt.Checked if data else Qt.Unchecked)
                self.table.setItem(row_idx, col_idx, item)
        conn.close()

    def add_user(self):
        try:
            conn = sqlite3.connect('users.db')
            c = conn.cursor()

            # 获取当前最大ID
            c.execute("SELECT MAX(user_id) FROM users")
            max_id = c.fetchone()[0]
            user_id = (max_id or 100) + 1  # 处理空表情况

            # 弹窗获取用户输入
            username, ok = QInputDialog.getText(self, "添加用户", "请输入用户名:")
            if not ok or not username:
                return

            # 选择头像文件
            avatar_path, _ = QFileDialog.getOpenFileName(self, "选择头像", "", "Images (*.png *.jpg)")
            if not avatar_path:
                avatar_path = "default.png"

            # 插入数据库
            new_user = (
                user_id,
                username,
                avatar_path,
                "123456",  # 默认密码
                0,  # 编码规则
                0,  # 未锁定
                datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                '这个人很懒，什么都没留下',
                'zhjw@example.com',
                '13800138000',
                '男',
                '2000-01-01'
            )
            c.execute("INSERT INTO users VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", new_user)
            conn.commit()
            self.load_data()
            QMessageBox.information(self, "成功", "用户添加成功")

        except sqlite3.IntegrityError:
            QMessageBox.critical(self, "错误", "用户名已存在")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"添加失败: {str(e)}")
        finally:
            conn.close()

    def delete_user(self):
        selected_row = self.table.currentRow()
        if selected_row >= 0:
            user_id = self.table.item(selected_row, 0).text()
            conn = sqlite3.connect('users.db')
            c = conn.cursor()
            c.execute("DELETE FROM users WHERE user_id=?", (user_id,))
            conn.commit()
            conn.close()
            self.load_data()
        else:
            QMessageBox.warning(self, "警告", "请先选择要删除的用户！")


# ========================== 启动程序 ==========================
if __name__ == "__main__":
    init_database()  # 初始化数据库

    app = QApplication(sys.argv)
    server_ui = ServerWindow()
    server_ui.show()
    sys.exit(app.exec_())


